#pragma once

#include <iostream>
#include <fstream>
#include <string>
#include <functional>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include "log.hpp"

using namespace std;
class file_util
{
public:
    static bool read(const std::string filename, std::string &body)
    {
        // 1.打开文件
        std::ifstream ifs(filename.c_str(), std::ios_base::in);
        if (ifs.is_open() == false)
        {
            return false;
        }
        // 2.获取文件大小
        ifs.seekg(0, std::ios::end);   // 将文件的读取位置移动到文件末尾处
        size_t filesize = ifs.tellg(); // 获取文件当前的读取位置
        ifs.seekg(0, std::ios::beg);
        // 3.将文件所有数据读取出来
        body.resize(filesize);
        ifs.read(&body[0], filesize);
        // 这里不能传递body.c_str()，因为c_str()返回的是const char*，我们的目的就是将内容读取到body里，body的内容必须是可修改的
        if (ifs.good() == false)
        {
            ifs.close(); // 释放资源，否则内存泄露
            return false;
        }
        // 4.关闭文件
        ifs.close();
        return true;
    }
    static bool write(const std::string filename, std::string body)
    {
        std::ofstream ofs(filename.c_str(), std::ios_base::out | std::ios_base::app);
        if (ofs.is_open() == false) 
        {
            return false;
        }
        ofs << body.c_str();
        if(ofs.good() == false)
        {
            ofs.close();
            return false;
        }
        ofs.close();
        return true;
    }
};

void serviceIO(int sockfd)
{
    char buffer[1024];

    while (true)
    {
        // 先从sockfd中读取消息, 然后再将消息返回
        size_t n = read(sockfd, buffer, sizeof(buffer) - 1);
        cout << buffer << " -> "<< n << endl;
        if (n == 0)
        {
            logMessage(NORMAL, "client quit, me too!");
            break;
            // read返回值为0代表client写端已经退出了,则读端break,与管道原理相同. 反过来如果读端退出, 写端进程会被OS发送SIGPIPE信号而终止.
        }
        if(buffer[0] == 'S')
        {
            // 目前把读到的数据当成字符串
            string body;
            file_util::read(buffer, body);
            cout << body<<endl;
            write(sockfd, body.c_str(), body.size());
        }
        else if(buffer[0] == 'T')
        {
            while(n = read(sockfd, buffer, sizeof(buffer) - 1) > 0)
            {
                string tmp;
                for(int i = 0; i < n; i++) tmp += buffer[i];
                
            }
            write(sockfd, "文件已经上传成功", 25);
        }
    }
    close(sockfd); // 线程处理完任务之后, 关闭套接字
}
class Task
{
    using func_t = std::function<void(int)>;

public:
    Task() {}
    Task(int sockfd, func_t func)
        : _sockfd(sockfd), _callback(func)
    {
    }
    void operator()()
    {
        _callback(_sockfd);
    }

private:
    int _sockfd;
    func_t _callback;
};
